import curses
import string
import argparse

# 定义列标签，跳过字母 'I'
columns = [chr(i) for i in range(ord('a'), ord('t') + 1) if chr(i) != 'i']

class GoBoard:
    def __init__(self, stdscr, file_name):
        self.stdscr = stdscr
        self.file_name = file_name
        self.board = [[0] * 19 for _ in range(19)]
        self.last_board = [[-1] * 19 for _ in range(19)]  # 初始化为 -1
        self.current_player = 1  # 1 for black, -1 for white
        self.cursor_pos = (0, 0)
        self.use_colors = False
        self.setup_curses()

        # 初始化调试文件
        self.debug_file = open(file_name, "w")

    def __del__(self):
        # 确保调试文件被关闭
        if hasattr(self, 'debug_file') and not self.debug_file.closed:
            self.debug_file.close()

    def setup_curses(self):
        curses.curs_set(0)  # 隐藏光标
        # 启用鼠标事件捕获
        curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)

    def print_board(self, full_refresh=True):
        if full_refresh:
            self.stdscr.clear()
        
            # 打印列标签
            columns = "ABCDEFGHJKLMNOPQRST"  # 棋盘列标签
            self.stdscr.addstr(0, 4, "   ")
            for idx, col in enumerate(columns):
                self.stdscr.addstr(0, 4 + idx * 2, f"{col.lower()}")
        
            for row in range(19):
                # 打印行号
                self.stdscr.addstr(row + 1, 0, f"{row+1:2}")
                for col in range(19):
                    x = 4 + col * 2
                    y = row + 1
                    self.print_cell(row, col, y, x)
                    if self.cursor_pos == (row, col):
                        self.stdscr.chgat(y, x, 1, curses.A_STANDOUT)
                # 打印行号在右侧
                self.stdscr.addstr(row + 1, 4 + 19 * 2, f"{row+1}")
        
            # 打印底部列标签
            self.stdscr.addstr(20, 4, "   ")
            for idx, col in enumerate(columns):
                self.stdscr.addstr(20, 4 + idx * 2, f"{col.lower()}")
        
            # 显示状态信息
            player_str = "Black" if self.current_player == 1 else "White"
            cursor_col = columns[self.cursor_pos[1]]
            cursor_row = self.cursor_pos[0] + 1
            self.stdscr.addstr(22, 0, f"Current Player: {player_str}, Cursor at: {cursor_col.lower()}{cursor_row}")
        
            self.stdscr.refresh()
        else:
            # 检测棋盘变化
            changes = self.detect_changes()

            # DEBUG hidden
            # self.debug_file.write(f"DEBUG: Single change at ({changes})\n")

            if len(changes) == 1:
                # 如果只有一个变化，更新该区域
                row, col = changes[0]
                x = 4 + col * 2
                y = row + 1
                self.print_cell(row, col, y, x)

                # DEBUG hidden
                # self.debug_file.write(f"DEBUG: Single change at ({row}, {col})\n")

                # 刷新屏幕
                self.stdscr.refresh()

            else:
                if len(changes) > 0:  # 检查 changes 是否不为空
                    # 如果有多个变化，更新整个棋盘
                    self.print_board(full_refresh=True)
                    self.debug_file.write(f"DEBUG: Full refresh due to multiple changes\n")
        
        # 更新 self.last_board
        self.last_board = [row[:] for row in self.board]

    def print_cell(self, row, col, y, x):
        if self.board[row][col] == 0:
            self.stdscr.addstr(y, x, "+", curses.A_DIM)
        elif self.board[row][col] == 1:
            if self.use_colors:
                self.stdscr.addstr(y, x, "●", curses.color_pair(1))
            else:
                self.stdscr.addstr(y, x, "●")
        elif self.board[row][col] == -1:
            if self.use_colors:
                self.stdscr.addstr(y, x, "○", curses.color_pair(2))
            else:
                self.stdscr.addstr(y, x, "○")

    def detect_changes(self):
        changes = []
        for row in range(19):
            for col in range(19):
                if self.board[row][col] != self.last_board[row][col]:
                    changes.append((row, col))

        # 增加调试日志，输出棋盘和上一次棋盘的状态
        # self.debug_file.write(f"DEBUG: Current board: {self.board}\n")
        # self.debug_file.write(f"DEBUG: Last board: {self.last_board}\n")

        return changes

    def check_win(self, player):
        # 检查水平、垂直、对角线是否连成5子
        for row in range(19):
            for col in range(19):
                if (col + 4 < 19 and 
                    all(self.board[row][col + i] == player for i in range(5))):
                    return True
                if (row + 4 < 19 and 
                    all(self.board[row + i][col] == player for i in range(5))):
                    return True
                if (row + 4 < 19 and col + 4 < 19 and 
                    all(self.board[row + i][col + i] == player for i in range(5))):
                    return True
                if (row + 4 < 19 and col - 4 >= 0 and 
                    all(self.board[row + i][col - i] == player for i in range(5))):
                    return True
        return False

    def run(self):
        with open(self.file_name, 'w') as f:
            while True:
                self.print_board()
                
                # 获取输入
                key = self.stdscr.getch()

                # 处理键盘输入
                if key == curses.KEY_RIGHT:
                    self.cursor_pos = (self.cursor_pos[0], min(self.cursor_pos[1] + 1, 18))
                elif key == curses.KEY_LEFT:
                    self.cursor_pos = (self.cursor_pos[0], max(self.cursor_pos[1] - 1, 0))
                elif key == curses.KEY_DOWN:
                    self.cursor_pos = (min(self.cursor_pos[0] + 1, 18), self.cursor_pos[1])
                elif key == curses.KEY_UP:
                    self.cursor_pos = (max(self.cursor_pos[0] - 1, 0), self.cursor_pos[1])
                elif key == ord(' '):
                    row, col = self.cursor_pos
                    if self.board[row][col] == 0:
                        self.board[row][col] = self.current_player
                        # 记录棋步到文件
                        move = f"Player {self.current_player}, enter your move (e.g., a1): {columns[col]}{row+1}\n"
                        f.write(move)
                        if self.check_win(self.current_player):
                            self.stdscr.addstr(23, 0, f"Player {self.current_player} wins!")
                            self.stdscr.refresh()
                            curses.napms(3000)
                            break
                        self.current_player = -self.current_player
                    else:
                        self.stdscr.addstr(23, 0, "This position is already occupied. Please choose another spot.", curses.A_BLINK)
                        self.stdscr.refresh()
                        curses.napms(1000)
                elif key == ord('q'):
                    break

                # 处理鼠标输入
                elif key == curses.KEY_MOUSE:
                    _, x, y, z, bstate = curses.getmouse()  # 获取鼠标事件
                    # 检查是否为双击事件
                    if bstate & curses.BUTTON1_DOUBLE_CLICKED:
                        # 将鼠标坐标转换为棋盘坐标
                        if y > 0 and y <= 20 and x >= 4 and x < 4 + 19 * 2:
                            row = y - 1
                            col = (x - 4) // 2
                            self.cursor_pos = (row, col)
                            if self.board[row][col] == 0:
                                self.board[row][col] = self.current_player
                                # 记录棋步到文件
                                move = f"Player {self.current_player}, enter your move (e.g., a1): {columns[col]}{row+1}\n"
                                f.write(move)
                                if self.check_win(self.current_player):
                                    self.stdscr.addstr(23, 0, f"Player {self.current_player} wins!")
                                    self.stdscr.refresh()
                                    curses.napms(3000)
                                    break
                                self.current_player = -self.current_player
                            else:
                                self.stdscr.addstr(23, 0, "This position is already occupied. Please choose another spot.", curses.A_BLINK)
                                self.stdscr.refresh()
                                curses.napms(1000)
                    else:
                        # 处理其他鼠标事件（如单击）
                        if y > 0 and y <= 20 and x >= 4 and x < 4 + 19 * 2:
                            row = y - 1
                            col = (x - 4) // 2
                            self.cursor_pos = (row, col)

def main(stdscr):
    parser = argparse.ArgumentParser(description="Go board game")
    parser.add_argument('file_name', type=str, help='File to save the game moves')
    args = parser.parse_args()

    go_board = GoBoard(stdscr, args.file_name)
    go_board.run()

if __name__ == "__main__":
    curses.wrapper(main)